const WebSocket = require('ws');
const { TelegramClient } = require('telegram');
const { StringSession } = require('telegram/sessions');
const { Api } = require('telegram/tl');
const fs = require('fs');
const path = require('path');

// 配置Telegram API（需从开发者平台获取）
const API_ID = 21054200; // 替换为你的API ID
const API_HASH = '21e56757e2968e685cf391fffde314a1'; // 替换为你的API Hash

// 常量定义
const TOKEN_DIR = path.join(__dirname, 'telegram_tokens'); // token存储目录
const WS_PORT = 8089; // WebSocket服务端口

// 初始化存储目录
if (!fs.existsSync(TOKEN_DIR)) {
  fs.mkdirSync(TOKEN_DIR, { recursive: true });
}

// 内存存储：账号状态管理
const accountStore = {
  clients: new Map(), // accountId => TelegramClient实例
  sessions: new Map(), // accountId => 会话字符串
  connections: new Map() // ws连接 => { accountId, eventHandler }
};

// 创建WebSocket服务器
const wss = new WebSocket.Server({ port: WS_PORT }, () => {
  console.log(`✅ WebSocket服务启动成功，监听 ws://127.0.0.1:${WS_PORT}`);
});

/**
 * 保存token到文件
 * @param {string} accountId 账号标识（如手机号）
 * @param {string} sessionString 会话字符串
 */
function saveTokenToFile(accountId, sessionString) {
  const safeAccountId = accountId.replace(/[^\w]/g, '_'); // 过滤特殊字符
  const filePath = path.join(TOKEN_DIR, `${safeAccountId}.json`);
  fs.writeFileSync(filePath, JSON.stringify({
    accountId,
    sessionString,
    updatedAt: new Date().toISOString()
  }, null, 2));
}

/**
 * 从文件加载token
 * @param {string} accountId 账号标识
 * @returns {string|null} 会话字符串
 */
function loadTokenFromFile(accountId) {
  const safeAccountId = accountId.replace(/[^\w]/g, '_');
  const filePath = path.join(TOKEN_DIR, `${safeAccountId}.json`);
  if (!fs.existsSync(filePath)) return null;
  
  try {
    const data = JSON.parse(fs.readFileSync(filePath, 'utf8'));
    return data.sessionString;
  } catch (err) {
    console.error(`加载token失败（${accountId}）:`, err);
    return null;
  }
}

/**
 * 删除token文件
 * @param {string} accountId 账号标识
 */
function deleteTokenFile(accountId) {
  const safeAccountId = accountId.replace(/[^\w]/g, '_');
  const filePath = path.join(TOKEN_DIR, `${safeAccountId}.json`);
  if (fs.existsSync(filePath)) {
    fs.unlinkSync(filePath);
  }
}

/**
 * 获取所有已保存的账号列表
 * @returns {Array} 账号信息数组
 */
function getAllSavedAccounts() {
  const accounts = [];
  if (!fs.existsSync(TOKEN_DIR)) return accounts;
  
  fs.readdirSync(TOKEN_DIR).forEach(filename => {
    if (filename.endsWith('.json')) {
      try {
        const data = JSON.parse(fs.readFileSync(path.join(TOKEN_DIR, filename), 'utf8'));
        accounts.push({
          accountId: data.accountId,
          isConnected: accountStore.clients.has(data.accountId),
          updatedAt: data.updatedAt
        });
      } catch (err) {
        console.error(`解析账号文件失败（${filename}）:`, err);
      }
    }
  });
  return accounts;
}

/**
 * 发送验证码
 * @param {string} phone 带国家码的手机号（如+8613800138000）
 * @returns {Promise<object>} 包含临时会话和phoneCodeHash的对象
 */
async function sendVerificationCode(phone) {
  const tempSession = new StringSession('');
  const client = new TelegramClient(tempSession, API_ID, API_HASH, {
    connectionRetries: 3
  });

  try {
    await client.connect();
    const result = await client.invoke(new Api.auth.SendCode({
      phoneNumber: phone,
      apiId: API_ID,
      apiHash: API_HASH,
      settings: new Api.CodeSettings({})
    }));
    return {
      tempSession: tempSession.save(),
      phoneCodeHash: result.phoneCodeHash,
      phone
    };
  } finally {
    await client.disconnect();
  }
}

/**
 * 完成登录（验证验证码）
 * @param {string} phone 手机号
 * @param {string} code 验证码
 * @param {string} tempSession 临时会话字符串
 * @param {string} phoneCodeHash 验证码哈希
 * @param {string} [password] 二步验证密码（可选）
 * @returns {Promise<string>} 正式会话字符串
 */
async function completeLogin(phone, code, tempSession, phoneCodeHash, password) {
  const client = new TelegramClient(new StringSession(tempSession), API_ID, API_HASH, {
    connectionRetries: 5
  });

  try {
    await client.connect();
    let authResult;

    // 尝试用验证码登录
    try {
      authResult = await client.invoke(new Api.auth.SignIn({
        phoneNumber: phone,
        phoneCodeHash: phoneCodeHash,
        phoneCode: code
      }));
    } catch (err) {
      // 处理二步验证
      if (err instanceof Api.Error && err.code === 401) {
        if (!password) throw new Error('需要二步验证密码');
        
        const passwordData = await client.invoke(new Api.account.GetPassword());
        const srp = await client.tlHelpers.computeSRP(password, passwordData);
        authResult = await client.invoke(new Api.auth.CheckPassword({
          password: new Api.InputCheckPasswordSRP({
            srpId: passwordData.srpId,
            a: srp.a,
            m1: srp.m1
          })
        }));
      } else {
        throw err;
      }
    }

    if (authResult instanceof Api.auth.Authorization) {
      return client.session.save(); // 返回正式会话
    } else {
      throw new Error('登录验证失败');
    }
  } finally {
    await client.disconnect();
  }
}

/**
 * 处理WebSocket消息
 * @param {WebSocket} ws 连接实例
 * @param {string} message 消息内容
 */
async function handleWsMessage(ws, message) {
  try {
    const data = JSON.parse(message);
    const { type, payload } = data;

    // 统一响应函数
    const sendResponse = (success, data = null, error = null) => {
      if (ws.readyState === WebSocket.OPEN) {
        ws.send(JSON.stringify({
          type: 'response',
          requestType: type,
          success,
          data,
          error
        }));
      }
    };

    switch (type) {
      // 1. 发送验证码
      case 'sendCode': {
        const { phone } = payload;
        const result = await sendVerificationCode(phone);
        sendResponse(true, {
          tempSession: result.tempSession,
          phoneCodeHash: result.phoneCodeHash,
          phone: result.phone
        });
        break;
      }

      // 2. 提交验证码完成登录
      case 'login': {
        const { accountId, phone, code, tempSession, phoneCodeHash, password } = payload;
        if (!accountId || !phone || !code || !tempSession || !phoneCodeHash) {
          return sendResponse(false, null, '缺少必要参数');
        }
        const sessionString = await completeLogin(phone, code, tempSession, phoneCodeHash, password);
        
        // 保存token到文件
        saveTokenToFile(accountId, sessionString);
        
        // 创建并存储客户端实例
        const client = new TelegramClient(new StringSession(sessionString), API_ID, API_HASH);
        await client.connect();
        accountStore.clients.set(accountId, client);
        accountStore.sessions.set(accountId, sessionString);
        
        // 绑定当前连接到账号
        accountStore.connections.set(ws, { accountId });
        
        // 启动私信监听
        setupPrivateMessageListener(client, ws, accountId);
        sendResponse(true, { accountId, message: '登录成功' });
        break;
      }

      // 3. 从已保存的token加载账号
      case 'loadAccount': {
        const { accountId } = payload;
        if (!accountId) return sendResponse(false, null, '缺少accountId');
        
        const sessionString = loadTokenFromFile(accountId);
        if (!sessionString) return sendResponse(false, null, '账号不存在');
        // 创建客户端并连接
        const client = new TelegramClient(new StringSession(sessionString), API_ID, API_HASH);
        await client.connect();
        accountStore.clients.set(accountId, client);
        accountStore.sessions.set(accountId, sessionString);
        // 绑定连接
        accountStore.connections.set(ws, { accountId });
        // 启动私信监听
        setupPrivateMessageListener(client, ws, accountId);
        sendResponse(true, { accountId, message: '账号加载成功' });
        break;
      }

      // 4. 注销账号
      case 'logout': {
        const { accountId } = payload;
        if (!accountId) return sendResponse(false, null, '缺少accountId');
        
        // 断开客户端连接
        const client = accountStore.clients.get(accountId);
        if (client) {
          await client.disconnect();
          accountStore.clients.delete(accountId);
        }
        
        // 删除token文件和内存记录
        deleteTokenFile(accountId);
        accountStore.sessions.delete(accountId);
        
        // 清除连接绑定
        if (accountStore.connections.get(ws)?.accountId === accountId) {
          accountStore.connections.delete(ws);
        }
        
        sendResponse(true, { message: '注销成功' });
        break;
      }
      // 5. 发送私信
      case 'sendPrivateMessage': {
        const { accountId, userId, text } = payload;
        if (!accountId || !userId || !text) {
          return sendResponse(false, null, '缺少参数（accountId, userId, text）');
        }
        const client = accountStore.clients.get(accountId);
        if (!client) return sendResponse(false, null, '账号未连接');
        // 发送消息
        await client.invoke(new Api.messages.SendMessage({
          peer: userId,
          message: text,
          randomId: BigInt(Math.floor(Math.random() * 1e18))
        }));
        
        sendResponse(true, { message: '消息发送成功' });
        break;
      }
      // 6. 获取已保存的账号列表
      case 'getAccountList': {
        const accounts = getAllSavedAccounts();
        sendResponse(true, { accounts });
        break;
      }
      default:
        sendResponse(false, null, `未知命令: ${type}`);
    }
  } catch (err) {
    console.error('消息处理错误:', err);
    if (ws.readyState === WebSocket.OPEN) {
      ws.send(JSON.stringify({
        type: 'error',
        message: err.message || '操作失败'
      }));
    }
  }
}

/**
 *  setup私信监听器（仅监听私信消息）
 * @param {TelegramClient} client 客户端实例
 * @param {WebSocket} ws 连接实例
 * @param {string} accountId 账号标识
 */
function setupPrivateMessageListener(client, ws, accountId) {
  const { NewMessage } = require('telegram/events');
  
  // 仅监听私信
  const eventHandler = async (event) => {
    if (!event.isPrivate) return; // 过滤非私信消息
    
    try {
      const message = event.message;
      const sender = await message.getSender();
      
      // 推送消息到客户端
      if (ws.readyState === WebSocket.OPEN) {
        ws.send(JSON.stringify({
          type: 'newPrivateMessage',
          data: {
            accountId,
            messageId: message.id.toString(),
            senderId: sender.id.toString(),
            senderName: sender.firstName || '未知用户',
            text: message.message || '',
            date: new Date(message.date * 1000).toISOString(),
            isOutgoing: message.out
          }
        }));
      }
    } catch (err) {
      console.error('私信监听错误:', err);
    }
  };
  
  // 添加事件监听
  client.addEventHandler(eventHandler, new NewMessage({}));
  
  // 连接关闭时移除监听
  ws.on('close', () => {
    client.removeEventHandler(eventHandler);
  });
}

// 处理WebSocket连接
wss.on('connection', (ws) => {
  console.log('🔗 新的WebSocket连接建立');
  
  // 处理消息
  ws.on('message', (data) => {
    handleWsMessage(ws, data.toString());
  });
  
  // 处理连接关闭
  ws.on('close', () => {
    const connInfo = accountStore.connections.get(ws);
    if (connInfo) {
      console.log(`🔌 连接关闭（账号: ${connInfo.accountId}）`);
      accountStore.connections.delete(ws);
    } else {
      console.log('🔌 连接关闭');
    }
  });
  
  // 处理错误
  ws.on('error', (err) => {
    console.error('WebSocket错误:', err);
  });
});

// 进程退出时清理资源
process.on('SIGINT', async () => {
  console.log('正在关闭所有客户端连接...');
  for (const [accountId, client] of accountStore.clients) {
    if (client.connected) {
      await client.disconnect();
    }
  }
  process.exit(0);
});